package com.studyproj.amap;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.ContextWrapper;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;

import com.amap.api.location.DPoint;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceClient;
import com.amap.api.fence.GeoFenceListener;

import static com.amap.api.fence.GeoFenceClient.GEOFENCE_IN;
import static com.amap.api.fence.GeoFenceClient.GEOFENCE_OUT;
import static com.amap.api.fence.GeoFenceClient.GEOFENCE_STAYED;

public class GeolocationModule extends ReactContextBaseJavaModule implements AMapLocationListener, GeoFenceListener {
    private final ReactApplicationContext reactContext;
    private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter;
    private static AMapLocationClient locationClient;
    private GeoFenceClient mGeoFenceClient;
    // 定义接收广播的action字符串
    private static final String GEOFENCE_BROADCAST_ACTION = "com.studyproj.amap.broadcast";

    GeolocationModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;

    }

    @Override
    public String getName() {
        return "AMapGeolocation";
    }

    @Override
    public void onLocationChanged(AMapLocation location) {
        if (location != null) {
            if (location.getErrorCode() == 0) {
                eventEmitter.emit("AMapGeolocation", toReadableMap(location));
            }
        } else {
            // 定位失败时，可通过ErrCode（错误码）信息来确定失败的原因，errInfo是错误信息，详见错误码表。
            Log.e("AmapError",
                    "location Error, ErrCode:" + location.getErrorCode() + ", errInfo:" + location.getErrorInfo());
        }
    }

    @ReactMethod
    public void initAMap() {
        if (locationClient != null) {
            locationClient.onDestroy();
        }

        locationClient = new AMapLocationClient(getReactApplicationContext());
        locationClient.setLocationListener(this);
        eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
    }

    @ReactMethod
    public void setOptions(ReadableMap options) {
        AMapLocationClientOption option = new AMapLocationClientOption();
        if (options.hasKey("interval")) {
            option.setInterval(options.getInt("interval"));
        }
        if (options.hasKey("reGeocode")) {
            option.setNeedAddress(options.getBoolean("reGeocode"));
        }
        locationClient.setLocationOption(option);
    }

    @ReactMethod
    public void start() {
        locationClient.startLocation();
    }

    @ReactMethod
    public void stop() {
        locationClient.stopLocation();
    }

    @ReactMethod
    public void getLastLocation(Promise promise) {
        Toast.makeText(getReactApplicationContext(), "getLastLocation", Toast.LENGTH_SHORT).show();
        promise.resolve(toReadableMap(locationClient.getLastKnownLocation()));
    }

    List<GeoFence> fenceList = new ArrayList<GeoFence>();

    @Override
    public void onGeoFenceCreateFinished(final List<GeoFence> geoFenceList, int errorCode, String customId) {
        if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {
            fenceList.addAll(geoFenceList);
            Toast.makeText(getReactApplicationContext(), "添加围栏成功!!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getReactApplicationContext(), "添加围栏失败!!", Toast.LENGTH_SHORT).show();
        }
    }

    @ReactMethod
    public void removeFence() {
        mGeoFenceClient.removeGeoFence();
    }

    @ReactMethod
    public void createFence() {
        mGeoFenceClient = new GeoFenceClient(getReactApplicationContext());
        mGeoFenceClient.createPendingIntent(GEOFENCE_BROADCAST_ACTION); // 创建并设置PendingIntent
        mGeoFenceClient.setGeoFenceListener(this);
        mGeoFenceClient.setActivateAction(GEOFENCE_IN);
        // 注册广播
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        filter.addAction(GEOFENCE_BROADCAST_ACTION);
        ContextWrapper wrapper = new ContextWrapper(getReactApplicationContext());
        wrapper.registerReceiver(mGeoFenceReceiver, filter);

        // 创建一个中心点坐标
        DPoint centerPoint = new DPoint();
        // 设置中心点纬度
        centerPoint.setLatitude(34.642743D);
        // 设置中心点经度
        centerPoint.setLongitude(112.371899D);
        mGeoFenceClient.addGeoFence(centerPoint, 100F, "电子围栏测试");
    }

    private ReadableMap toReadableMap(AMapLocation location) {
        if (location != null) {
            WritableMap map = Arguments.createMap();
            map.putDouble("timestamp", location.getTime());
            map.putDouble("accuracy", location.getAccuracy());
            map.putDouble("latitude", location.getLatitude());
            map.putDouble("longitude", location.getLongitude());
            map.putDouble("altitude", location.getAltitude());
            map.putDouble("speed", location.getSpeed());
            if (!location.getAddress().isEmpty()) {
                map.putString("address", location.getAddress());
                map.putString("description", location.getDescription());
                map.putString("poiName", location.getPoiName());
                map.putString("country", location.getCountry());
                map.putString("province", location.getProvince());
                map.putString("city", location.getCity());
                map.putString("cityCode", location.getCityCode());
                map.putString("district", location.getDistrict());
                map.putString("street", location.getStreet());
                map.putString("streetNumber", location.getStreetNum());
                map.putString("adCode", location.getAdCode());
            }
            return map;
        }
        return null;
    }

    /**
     * 接收触发围栏后的广播,当添加围栏成功之后，会立即对所有围栏状态进行一次侦测，如果当前状态与用户设置的触发行为相符将会立即触发一次围栏广播；
     * 只有当触发围栏之后才会收到广播,对于同一触发行为只会发送一次广播不会重复发送，除非位置和围栏的关系再次发生了改变。
     */
    private BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 接收广播
            if (intent.getAction().equals(GEOFENCE_BROADCAST_ACTION)) {
                Bundle bundle = intent.getExtras();
                String customId = bundle.getString(GeoFence.BUNDLE_KEY_CUSTOMID);
                String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);
                // status标识的是当前的围栏状态，不是围栏行为
                int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);
                StringBuffer sb = new StringBuffer();

                switch (status) {
                case GeoFence.STATUS_LOCFAIL:
                    sb.append("定位失败");
                    // sb.append(bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS)); //
                    // 定位失败原因，参考https://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode
                    break;
                case GeoFence.STATUS_IN:
                    sb.append("进入围栏 ");
                    break;
                case GeoFence.STATUS_OUT:
                    sb.append("离开围栏 ");
                    break;
                case GeoFence.STATUS_STAYED:
                    sb.append("停留在围栏内 ");
                    break;
                default:
                    break;
                }
                if (status != GeoFence.STATUS_LOCFAIL) {
                    if (!TextUtils.isEmpty(customId)) {
                        sb.append(" customId: " + customId);
                    }
                    sb.append(" fenceId: " + fenceId);
                }

                Toast.makeText(getReactApplicationContext(), sb.toString(), Toast.LENGTH_SHORT).show();
            }
        }
    };
}
